#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>

#include "Common.hpp"
#include "Log.hpp"

using namespace LogModule;

const std::string Sep = "\r\n";
const std::string LineSep = " ";
const std::string HeaderLineSep = ": ";
const std::string BlankLine = Sep;
const std::string defaulthomepage = "wwwroot";
const std::string http_version = "HTTP/1.0";
const std::string page404 = "wwwroot/404.html";
const std::string firstpage = "index.html";

class HttpRequest
{
public:
    HttpRequest()
    {
    }
    ~HttpRequest()
    {
    }

    bool IsHasArgs()
    {
        return _isexec;
    }

    // GET /favicon.ico HTTP/1.1\r\n
    // Host: 8.137.19.140:8080
    // Connection: keep-alive
    // User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0
    // Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
    // Referer: http://8.137.19.140:8080/?msg=i_have_sent_a_message_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_he_
    // Accept-Encoding: gzip, deflate
    // Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
    // dnt: 1
    // sec-gpc: 1
    //

    bool ParseHeaderkv()
    {
        std::string key, value;
        for (auto &header : _req_header)
        {
            if (SplitString(header, HeaderLineSep, &key, &value))
            {
                _headerkv.insert(std::make_pair(key, value));
            }
        }
        return true;
    }

    bool ParseHeader(std::string &request_str)
    {
        std::string line;
        while (true)
        {
            bool r = ParseOneLine(request_str, &line, Sep);
            if (r && !line.empty())
            {
                _req_header.push_back(line);
            }
            else if (r && line.empty())
            {
                _blank_line = Sep;
                break;
            }
            else
            {
                return false;
            }
        }
        ParseHeaderkv();
        return true;
    }

    // GET /favicon.ico HTTP/1.1
    // Host: 110.41.55.240:8081
    // Connection: keep-alive
    // User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0
    // Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
    // Referer: http://110.41.55.240:8081/
    // Accept-Encoding: gzip, deflate
    // Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

    void Deserialize(std::string &request_str)
    {
        std::cout << "+++++++++++++++++++" << std::endl;
        if (ParseOneLine(request_str, &_req_line, Sep))
        {
            // 提取请求行中的详细字段
            ParseReqLine(_req_line, LineSep);
            ParseHeader(request_str);
            _body = request_str;

            // 分析请求
            if (_method == "POST")
            {
                _isexec = true; // 参数在正文
                _args = _body;
                _path = _uri;
                LOG(LogLevel::DEBUG) << "POST: _path: " << _path;
                LOG(LogLevel::DEBUG) << "POST: _args: " << _path;
            }
            else if (_method == "GET")
            {
                auto pos = _uri.find("?");
                if (pos != std::string::npos)
                {
                    _isexec = true;
                    _path = _uri.substr(0, pos);
                    _args = _uri.substr(pos + 1);
                    LOG(LogLevel::DEBUG) << "POST: _path: " << _path;
                    LOG(LogLevel::DEBUG) << "POST: _args: " << _path;
                }
            }
        }

        std::cout << "+++++++++++++++++++" << std::endl;
    }
    std::string GetContent(const std::string path)
    {
        std::string content;
        std::ifstream in(path, std::ios::binary);
        if(!in.is_open())
            return std::string();

        in.seekg(0, in.end);//将文件指针移动到末尾。
        int filesize = in.tellg(); //获取当前文件指针的位置（即文件大小，单位为字节）。
        in.seekg(0,in.beg);//将文件指针移回开头，准备读取内容。

        content.resize(filesize);
        in.read((char*)content.c_str(),filesize);

        in.close();
        LOG(LogLevel::DEBUG) << "content length: "<< content.size();
        return content;

        // 暂时做法
        // LOG(LogLevel::DEBUG) << "_uri: " << _uri;

        // std::string content;
        // std::ifstream in(_uri);
        // if (!in.is_open())
        //     return std::string();

        // std::string line;
        // while (std::getline(in, line))//原因是getline
        // {
        //     content += line;
        // }

        // in.close();
        // return content;
    }
    // std::string GetContent(const std::string path)
    // {
    //     // std::string content;
    //     // std::ifstream in(path, std::ios::app);
    //     // if(!in.is_open())
    //     //     return std::string();

    //     // in.seekg(0, in.end);

    //     // 暂时做法
    //     std::string content;
    //     std::ifstream in(_uri);
    //     if (!in.is_open())
    //         return std::string();

    //     std::string line;
    //     while (std::getline(in, line))
    //     {
    //         content += line;
    //     }

    //     in.close();
    //     return content;
    // }

    void Print()
    {
        std::cout << "_method : " << _method << std::endl;
        std::cout << "_uri : " << _uri << std::endl;
        std::cout << "_version : " << _version << std::endl;
        for (auto &kv : _headerkv)
        {
            std::cout << kv.first << ":" << kv.second << std::endl;
        }
        std::cout << "_blank_line : " << _blank_line << std::endl;
        std::cout << "_body : " << _body << std::endl;
    }

    std::string Uri()
    {
        return _uri;
    }

    void SetUri(const std::string newuri)
    {
        _uri = newuri;
    }

    std::string Path() { return _path; }
    std::string Args() { return _args; }

    std::string Suffix()
    {
        // _uri ->wwwroot/index.html wwwroot/image/1.jpg wwwroot/login.html
        auto pos = _uri.rfind(".");
        if (pos == std::string::npos)
            return std::string(".html");
        else
            return _uri.substr(pos);
    }

private:
    // GET /favicon.ico HTTP/1.1
    void ParseReqLine(std::string _req_line, const std::string &LineSep)
    {
        (void)LineSep;
        std::stringstream ss(_req_line);
        ss >> _method >> _uri >> _version;
        // _uri = defaulthomepage + _uri;
    }

private:
    std::string _req_line;
    std::vector<std::string> _req_header;
    std::string _blank_line;
    std::string _body; //   body内部可能包含参数

    // 在反序列化的过程中，细化我们解析出来的手段
    std::string _method; // 请求方法
    std::string _uri;    // 请求服务器的资源路径 用户想要这个 、、login.html || /login/xxxx
    std::string _path;
    std::string _args;
    std::string _version;
    std::unordered_map<std::string, std::string> _headerkv;

    bool _isexec = false;
};

// 对于http, 任何请求, 都要有应答
class HttpResponse
{
public:
    HttpResponse() : _version(http_version), _blank_line(Sep)
    {
    }
    ~HttpResponse()
    {
    }

    void Build(HttpRequest &req)
    {
        // std::string uri = req.Uri(); // wwwroot/ /wwroot/a/b
        // if (uri.back() == '/')
        // {
        //     _status_code = 301;
        //     _status_desc = Code2Desc(_status_code); // 和状态码是强相关联的
        //     // SetHeader("Location", "http://110.41.55.240:8081/register.html");
        //     for (auto &header : _header_kv)
        //     {
        //         _resp_header.push_back(header.first + HeaderLineSep + header.second);
        //     }
        //     LOG(LogLevel::DEBUG) << "------客户端在请求: " << req.Uri();
        // }

        // _content = req.GetContent();
        // if (_content.empty())
        // {
        //     // 用户请求的资源不存在
        //     _status_code = 404;
        //     req.SetUri(page404);
        //     _content = req.GetContent();
        // }
        // else
        // {
        //     _status_code = 200;
        // }
        // _status_desc = Code2Desc(_status_code); // 与状态码强关联

        std::string uri = defaulthomepage + req.Uri(); ////wwwroot/ /wwroot/a/b
        if(uri.back() == '/')
        {
            uri += firstpage; //wwwroot/index.html
            // req.SetUri(uri);
        }
        LOG(LogLevel::DEBUG) << "----客户端在请求: " <<req.Uri();
        req.Print();
        LOG(LogLevel::DEBUG) << "---------------------------";

        _content = req.GetContent(uri);
        LOG(LogLevel::DEBUG) << "content length: "<< _content.size();

        if(_content.empty())
        {
            //用户请求的资源并不存在
            _status_code = 404;
            // req.SetUri(page404);
            _content = req.GetContent(page404);
        }
        else
        {
            _status_code = 200;
        }

        _status_desc = Code2Desc(_status_code); ////与状态码强相关的!
        if(!_content.empty())
        {
            SetHeader("Content-Length", std::to_string(_content.size()));
        }    
        std::string mime_type = Suffix2Desc(req.Suffix());

        SetHeader("Content_type", mime_type);
        _body = _content;
    }

    void SetCode(int code)
    {
        _status_code = code;
        _status_desc = Code2Desc(_status_code);
    }

    void SetBody(const std::string &body)
    {
        _body = body;
    }

    void SetHeader(const std::string &k, const std::string &v)
    {
        _header_kv[k] = v;
    }

    void Serialize(std::string *resp_str)
    {
        for (auto &header : _header_kv)
        {
            _resp_header.push_back(header.first + HeaderLineSep + header.second);
        }
        _resp_line = _version + LineSep + std::to_string(_status_code) + LineSep + _status_desc + Sep;

        // 序列化
        *resp_str = _resp_line;
        for (auto &line : _resp_header)
        {
            *resp_str += (line + Sep);
        }
        *resp_str += _blank_line;
        *resp_str += _body;
    }

private:
    std::string Code2Desc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
            break;
        case 404:
            return "Not Found";
            break;
        case 301:
            return "Moved Permanently";
            break;
        case 302:
            return "Found";
            break;
        default:
            return std::string();
        }
    }

    std::string Suffix2Desc(const std::string &suffix)
    {
        if(suffix == ".html")
            return "text/html";
        else if(suffix == ".jpg")
            return "application/x-jpg";
        else
            return "text/html";
    }

private:
    // 必备的要素
    std::string _version;
    int _status_code;
    std::string _status_desc; // 状态码描述
    std::string _content;
    std::unordered_map<std::string, std::string> _header_kv;

    // 最终要这四部分构建应答
    std::string _resp_line; //请求行
    std::vector<std::string> _resp_header; // 回应报头
    std::string _blank_line; //空行
    std::string _body;  //请求正文
};